package view;

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import modelInterfaces.ITest;
import utils.Codes;
import utils.Messages;
import viewInterfaces.IViewTestPanel;
import controllerInterfaces.IControllerTestsPanel;

/**
 * Panel used for managing the list of test: add, edit, delete and copy.
 * 
 * @author Andy Cullache
 */
public class ViewTestPanel extends JPanel implements IViewTestPanel {

	private IControllerTestsPanel myController;
	private JList<ITest> list;
	private JButton btnAdd;
	private JButton btnEdit;
	private JButton btnRemove;
	private JButton btnCopy;
	
	/**
	 * Default constructor. Create the panel.
	 */
	public ViewTestPanel() {		
		JPanel panel = new JPanel();

		panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		
		btnAdd = new JButton("Add");
		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				StartToAddTestSetup();
			}
		});
		panel.add(btnAdd);
		
		btnEdit = new JButton("Edit");
		btnEdit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {				
				if (!list.isSelectionEmpty()){
					StartToEditTestSetup(list.getSelectedValue());
				}
				else
				{
					renderError(Codes.errorEditListObject, Messages.errorEditListObject);
				}				
			}
		});
		panel.add(btnEdit);
		
		btnRemove = new JButton("Remove");
		btnRemove.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (!list.isSelectionEmpty()) {
					Object[] options = { "Yes", "No" };
					int n = JOptionPane
							.showOptionDialog(
									null,
									"Are you sure you want to remove test?",
									"Remove test",
									JOptionPane.YES_NO_CANCEL_OPTION,
									JOptionPane.QUESTION_MESSAGE, null,
									options, options[1]);
					if (n == 0) {
						myController.removeTest(list.getSelectedValue());
						setTestUpdate();
					}
				}
				else
				{
					renderError(Codes.errorRemoveListObject, Messages.errorRemoveListObject);
				}	
			}
		});
		
		panel.add(btnRemove);
		
		btnCopy = new JButton("Copy");
		btnCopy.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(!list.isSelectionEmpty()){
					StartToCopyTestSetup(list.getSelectedValue());
					setTestUpdate();
				}
				else
				{
					renderError(Codes.errorCopyListObject, Messages.errorCopyListObject);
				}
			}
		});
		
		panel.add(btnCopy);
				
		JScrollPane scrollPane = new JScrollPane();
		GroupLayout groupLayout = new GroupLayout(this);
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.TRAILING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
						.addComponent(scrollPane, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE)
						.addComponent(panel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE))
					.addContainerGap())
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addComponent(panel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 234, Short.MAX_VALUE)
					.addContainerGap())
		);
		
		list = new JList();
		list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		list.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent arg0) {
				if(list.isSelectionEmpty())
				{
					btnEdit.setEnabled(false);
					btnRemove.setEnabled(false);
					btnCopy.setEnabled(false);
				}
				else
				{
					btnEdit.setEnabled(true);
					btnRemove.setEnabled(true);
					btnCopy.setEnabled(true);
				}
			}
		});
		
		
		scrollPane.setViewportView(list);
		setLayout(groupLayout);
	}
	


	/**
	 * Mark with a String "--Error" to the test to be defective, do not have metrics and algorithms associated.
	 */
	public void setTestUpdate(){
		DefaultListModel models = new DefaultListModel();		
		for(ITest test: this.myController.getTests()){
			if(test.getName().endsWith("--Error")){
				String aux = test.getName().replaceAll("--Error", "");
				test.setName(aux);
			}
			if(test.getAlgorithms().size()==0 || test.getMetrics().size()==0)
				test.setName(test.getName()+"--Error");
			models.addElement(test);
		}
		list.setModel(models);
	}

	@Override
	public JPanel GetPanel() {
		return this;
	}

	/**
	 * Sets the controller of this view.
	 * 
	 * @param myController      Test panel controller.
	 */
	@Override
	public void SetController(IControllerTestsPanel myController) {
		this.myController = myController;
	}


	/**
	 * Method used to display error messages with the respective code.
	 * 
	 * @param code      Error code.
	 * @param message      Message code.
	 */
	public void renderError(int code, String message) {
		javax.swing.JOptionPane.showMessageDialog(this, code + " - " + message, "Error",javax.swing.JOptionPane.ERROR_MESSAGE);	
	}
	

	
	/**
	 * Start process for add a new test setup.
	 */
	public void StartToAddTestSetup() {
		if(myController.getDBConnectedStatus() == true)
		{
			myController.startTestSetup();
		}
		else
		{
			renderError(Codes.DBconnectionDoesntExist, Messages.DBconnectionDoesntExist);
		}
	}	
	

	
	/**
	 * Start process for edit a existing test setup.
	 * @param index index of test setup to edit
	 */
	public void StartToEditTestSetup(ITest test) {
		if(myController.getDBConnectedStatus() == true)
		{
			myController.editTestSetup(test);
		}
		else
		{
			renderError(Codes.DBconnectionDoesntExist, Messages.DBconnectionDoesntExist);
		}
	}
	
	
	
	/**
	 * Start process for remove a existing test setup.
	 * @param index index of test setup to remove
	 */
	public void StartToRemoveTestSetup(ITest test) {
		myController.removeTest(test);
	}

	
	/**
	 * Start process for copy a existing test setup.
	 * @param index index of test setup to copy
	 */
	public void StartToCopyTestSetup(ITest test) {
		myController.copyTest(test);
	}
	
	
	/**
	 * Enables or disables all component of this panel, depending on the value of the parameter value.</br> 
	 * @param value	- If true, this component is enabled; otherwise this component is disabled  .
	 */	
	public void setEnabledAll(boolean value) {
		Component[] components = this.getComponents();  
		for (int i = 0; i < components.length; i++) 
		{ 
			if( components[i] instanceof JPanel)
			{
				this.setPanelComponentsEnabled(value, (JPanel) components[i]);
			}
		} 
	}
	

	/**
	 * Enables or disables all components depending on the value of the parameter value and parameter panel</br> 
	 * @param value	- If true, this component is enabled; otherwise this component is disabled  .
	 * @param panel - JPanel that contains components 
	 */	
	private void setPanelComponentsEnabled(boolean value, JPanel panel)
	{
		Component[] components = panel.getComponents(); 
		for (int i = 0; i < components.length; i++) 
		{ 
			components[i].setEnabled(value); 
		} 		
	}	
}
